package com.tanhua.server.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.RandomUtil;
import com.alibaba.fastjson.JSON;
import com.tanhua.autoconfig.template.HuanXinTemplate;
import com.tanhua.commons.utils.Constants;
import com.tanhua.dubbo.api.*;
import com.tanhua.model.domain.Question;
import com.tanhua.model.domain.UserInfo;
import com.tanhua.model.dto.QuestionDto;
import com.tanhua.model.dto.RecommendUserDto;
import com.tanhua.model.mongo.RecommendUser;
import com.tanhua.model.mongo.Visitors;
import com.tanhua.model.vo.ErrorResult;
import com.tanhua.model.vo.NearUserVo;
import com.tanhua.model.vo.PageResult;
import com.tanhua.model.vo.TodayBest;
import com.tanhua.server.exception.BusinessException;
import com.tanhua.server.interceptor.UserHolder;
import com.tanhua.server.service.MessagesService;
import com.tanhua.server.service.TanhuaService;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author wjs
 * @version 1.0
 * @date 2021/12/25 0025 下午 7:55
 */
@Service
public class TanhuaServiceImpl implements TanhuaService {
    @DubboReference
    private RecommendUserApi recommendUserApi;

    @DubboReference
    private UserInfoApi userInfoApi;

    @DubboReference
    private QuestionApi questionApi;

    @Autowired
    HuanXinTemplate huanXinTemplate;

    @DubboReference
    private UserLikeApi userLikeApi;

    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private MessagesService messagesService;

    @DubboReference
    private UserLocationApi userLocationApi;

    @DubboReference
    private VisitorsApi visitorsApi;

    @Value("${RecommendUser.userId}")
    private Long recommendUserId;

    //指定默认数据
    @Value("${tanhua.default.recommend.users}")
    private String recommendUser;

    //查询今日佳人数据
    @Override
    public TodayBest todayBest() {
        //1 获取用户id
        Long userId = UserHolder.getUserId();
        //2 调用API查询
        RecommendUser recommendUser = recommendUserApi.queryWithMaxScore(userId);
        if (recommendUser == null) {
            recommendUser = new RecommendUser();
            recommendUser.setUserId(recommendUserId);
        }
        //3 将RecommendUser转化为TodayBest对象
        UserInfo userInfo = userInfoApi.findById(recommendUser.getUserId());
        TodayBest todayBest = TodayBest.init(userInfo, recommendUser);
        //4 返回
        return todayBest;
    }

    //查询分页推荐好友列表
    @Override
    public PageResult recommendation(RecommendUserDto dto) {
        //1、获取用户id
        Long userId = UserHolder.getUserId();
        //2、调用recommendUserApi分页查询数据列表（PageResult -- RecommendUser）
        PageResult pageResult = recommendUserApi.queryRecommendUserList(dto.getPage(), dto.getPagesize(), userId);
        //3、获取分页中的RecommendUser数据列表
        List<RecommendUser> items = (List<RecommendUser>) pageResult.getItems();
        //4、判断列表是否为空
        if (items == null || items.size() <= 0) {
            return pageResult;
        }
        //5、提取所有推荐的用户id列表
        List<Long> ids = items.stream().map(RecommendUser::getUserId).collect(Collectors.toList());
//        List<Long> ids = CollUtil.getFieldValues(items, "userId", Long.class);
        UserInfo userInfo = new UserInfo();
        userInfo.setAge(dto.getAge());
        userInfo.setGender(dto.getGender());
        //6、构建查询条件，批量查询所有的用户详情
        Map<Long, UserInfo> map = userInfoApi.findByIds(ids, userInfo);
        //7、循环推荐的数据列表，构建vo对象
        List<TodayBest> list = items.stream()
                .filter(item -> map.get(item.getUserId()) != null)
                .map((item) -> {
                    return TodayBest.init(map.get(item.getUserId()), item);
                }).collect(Collectors.toList());
//        List<TodayBest> list = new ArrayList<>();
//        for (RecommendUser item : items) {
//            UserInfo info = map.get(item.getUserId());
//            if(info!=null) {
//                TodayBest vo = TodayBest.init(info, item);
//                list.add(vo);
//            }
//        }
        //8、构造返回值
        pageResult.setItems(list);
        return pageResult;
    }

    @Override
    public TodayBest personalInfo(Long userId) {

        //1、根据用户id查询，用户详情
        UserInfo userInfo = userInfoApi.findById(userId);
        //2、根据操作人id和查看的用户id，查询两者的推荐数据
        RecommendUser recommendUser = recommendUserApi.queryByUserId(userId, UserHolder.getUserId());

        //构造访客数据，调用API保存
        Visitors visitors = new Visitors();
        visitors.setUserId(userId);
        visitors.setVisitorUserId(UserHolder.getUserId());
        visitors.setFrom("首页");
        visitors.setDate(System.currentTimeMillis());
        visitors.setVisitDate(new SimpleDateFormat("yyyyMMdd").format(new Date()));
        visitors.setScore(recommendUser.getScore());
        visitorsApi.save(visitors);
        //3、构造返回值
        return TodayBest.init(userInfo, recommendUser);
    }

    @Override
    public String strangerQuestions(Long userId) {
        Question question = questionApi.findByUserId(userId);

        return question == null ? "暂无问题" : question.getTxt();
    }

    @Override
    public void replyQuestions(QuestionDto questionDto) {
        //查询当前用户信息
        Long userId = UserHolder.getUserId();
        UserInfo userInfo = userInfoApi.findById(userId);

        Map map = new HashMap<>();
        //当前用户信息填充
        map.put("userId", userId);
        map.put("huanXinId", Constants.HX_USER_PREFIX + userId);
        map.put("nickname", userInfo.getNickname());
        //陌生人问题填充
        map.put("strangerQuestion", questionApi.findByUserId(questionDto.getUserId()));
        //当前用户回复陌生人问题
        map.put("reply", questionDto.getReply());
        //转json
        String message = JSON.toJSONString(map);

        //调用template对象，发送消息
        //sendMsg()   1、接受方的环信id，2、消息
        Boolean aBoolean = huanXinTemplate.sendMsg(Constants.HX_USER_PREFIX + questionDto.getUserId(), message);
        if (!aBoolean) {
            throw new BusinessException(ErrorResult.error());
        }
    }

    @Override
    public List<TodayBest> queryCardsList() {
        //1、调用推荐API查询数据列表（排除喜欢/不喜欢的用户，数量限制）
        List<RecommendUser> users = recommendUserApi.queryCardsList(UserHolder.getUserId(), 10);
        //2、判断数据是否存在，如果不存在，构造默认数据 1,2,3
        if (CollUtil.isEmpty(users)) {
            users = new ArrayList<>();
            String[] userIds = recommendUser.split(",");
            users = Arrays.stream(userIds).map(userId -> {
                RecommendUser recommendUser = new RecommendUser();
                recommendUser.setUserId(Long.valueOf(userId));
                recommendUser.setToUserId(UserHolder.getUserId());
                recommendUser.setScore(RandomUtil.randomDouble(60, 90));
                return recommendUser;
            }).collect(Collectors.toList());
        }
        //3、构造VO
        List<Long> ids = users.stream().map(RecommendUser::getUserId).collect(Collectors.toList());
        if (CollUtil.isEmpty(ids)) {
            return new ArrayList<>();
        }
        Map<Long, UserInfo> infoMap = userInfoApi.findByIds(ids, null);

        List<TodayBest> vos = users.stream().filter(user -> infoMap.get(user.getUserId()) != null)
                .map(user -> {
                    return TodayBest.init(infoMap.get(user.getUserId()), user);
                }).collect(Collectors.toList());

        return vos;
    }

    @Override
    public void likeUser(Long likeUserId) {
        //1、调用API，保存喜欢数据(保存到MongoDB中)
        Boolean save = userLikeApi.saveOrUpdate(UserHolder.getUserId(), likeUserId, true);
        if (!save) {
            //失败
            throw new BusinessException(ErrorResult.error());
        }
        //2、操作redis，写入喜欢的数据，删除不喜欢的数据 (喜欢的集合，不喜欢的集合)
        redisTemplate.opsForSet().remove(Constants.USER_NOT_LIKE_KEY + UserHolder.getUserId(), likeUserId.toString());
        redisTemplate.opsForSet().add(Constants.USER_LIKE_KEY + UserHolder.getUserId(), likeUserId.toString());
        //3、判断是否双向喜欢
        if (isLike(likeUserId, UserHolder.getUserId())) {
            //4、添加好友
            messagesService.contacts(likeUserId);
        }
    }

    @Override
    public void notLikeUser(Long likeUserId) {
        //1、调用API，保存喜欢数据(保存到MongoDB中)
        Boolean save = userLikeApi.saveOrUpdate(UserHolder.getUserId(), likeUserId, false);
        if (!save) {
            //失败
            throw new BusinessException(ErrorResult.error());
        }
        //2、操作redis，写入喜欢的数据，删除不喜欢的数据 (喜欢的集合，不喜欢的集合)
        redisTemplate.opsForSet().add(Constants.USER_NOT_LIKE_KEY + UserHolder.getUserId(), likeUserId.toString());
        redisTemplate.opsForSet().remove(Constants.USER_LIKE_KEY + UserHolder.getUserId(), likeUserId.toString());
        //3. 判断是否双向喜欢，删除好友
    }

    @Override
    public List<NearUserVo> queryNearUser(String gender, String distance) {
        //1、调用API查询附近的用户（返回的是附近的人的所有用户id，包含当前用户的id）
        List<Long> userIds = userLocationApi.queryNearUser(UserHolder.getUserId(), Double.valueOf(distance));
        //2、判断集合是否为空
        if (CollUtil.isEmpty(userIds)) {
            return new ArrayList<>();
        }
        //3、调用UserInfoApi根据用户id查询用户详情
        UserInfo userInfo = new UserInfo();
        userInfo.setGender(gender);
        Map<Long, UserInfo> map = userInfoApi.findByIds(userIds, userInfo);
        //4、构造返回值。
        List<NearUserVo> vos = userIds.stream().filter(userId -> !UserHolder.getUserId().equals(userId))
                .filter(userId -> map.get(userId) != null)
                .map(userId -> NearUserVo.init(map.get(userId)))
                .collect(Collectors.toList());

        return vos;
    }

    //判断是否双向喜欢
    public Boolean isLike(Long userId, Long likeUserId) {
        String key = Constants.USER_LIKE_KEY + userId;
        return redisTemplate.opsForSet().isMember(key, likeUserId.toString());
    }
}
